<?php 

class Kernel_Response_File extends Kernel_Filter 
{
    
    /**
     * @desc Mime-type by default.
     *
     */
    const DEFAULT_MIMETYPE = 'application/octet-stream';
    
    /**
    * @desc Default mime-type.
    * 
    * @param string
    */
    protected $_mime_type = self::DEFAULT_MIMETYPE;
    
    /**
    * @desc File name.
    * 
    * @param string
    */
    protected $_basename; 
    
    /**
    * @desc Path to file.
    * 
    * @param string
    */
    protected $_dirname; 
    
    /**
    * @desc File to output.
    * 
    * @param string
    */
    private $_file; 
    
    /**
     * @desc Start filter.
     *
     */
    public function process()
    {
        if (is_null($this->_basename)) {
            $this->_basename = Application::getRequest()->get('file');
        }
        
        // even if file name is set in overlayed method return file basename to 
        // prevent possibility of using smth like this "file=../../../etc/passwd"
        $this->_file = $this->_dirname . basename($this->_basename);
        
        if (!$this->_exists()) {
            $this->_abort('File not found');
        }
        
        // parent control file access by _allowed() method
        parent::process();
        
        $this->_output();
    }
    
    /**
    * @desc Check whether file exists.
    * 
    * @return boolean
    */
    private function _exists() 
    {
        return is_file($this->_file);
    }
    
    /**
     * @desc Output file to browser. 
     *
     * @param   string  $path
     */
    private function _output() 
    {
        Application::getResponse()->header(array(
                  'Cache-Control' => 'maxage=3600', // tell ugly IE that cach can be done
                         'Pragma' => 'public',      // and it's public
                   'Content-Type' => $this->_mime_type, 
            'Content-Disposition' => 'attachment; filename="' . $this->_basename . '"',
                 'Content-Length' => filesize($this->_file),
        ))->readfile($this->_file);
    }
    
}